
{***********************************************************}
{                                                           }
{      Informix Data Access Components                      }
{                                                           }
{      Informix Values                                      }
{                                                           }
{      Copyright (c) 2001-2008 Luxena Software Company      }
{      http://www.luxena.com                                }
{      e-mail: support@luxena.com                           }
{                                                           }
{***********************************************************}

unit IfxValues;

{$I lx.inc}

interface

uses
  Classes, DB, LXClasses, LXDBTypes, IfxTypes, IfxDecimal, IfxDateTime,
  IfxLocator, IfxInt8, IfxConnection, IfxLob;


type

{ IIfxValue }

  IIfxValue = interface
    ['{6D85AA3A-6720-4B79-A370-6D9116E6E490}']

    function GetIsNull: Boolean;
    function GetAsBCD: TBcd;
    function GetAsBoolean: Boolean;
    function GetAsByte: TBlobByteData;
    function GetAsCurrency: Currency;
    function GetAsDate: int4;
    function GetAsDateTime: TDateTime;
    function GetAsDecimal: TDecimal;
    function GetAsDTime: TDTime;
    function GetAsFloat: Double;
    function GetAsInt8: TIfx_int8;
    function GetAsInteger: Integer;
    function GetAsInterval: Intrvl;
    function GetAsLargeint: Largeint;
    function GetAsLob: IIfxLob;
    function GetAsLocator: PLoc;
    function GetAsSmallFloat: Single;
    function GetAsSmallInt: int2;
    function GetAsSQLTimeStamp: TSQLTimeStamp;
    function GetAsString: string;
    function GetAsTime: TDateTime;
    function GetAsVariant: Variant;

    procedure SetNull;
    procedure SetAsBCD(const Value: TBcd);
    procedure SetAsBlob(const Value: IIfxLob);
    procedure SetAsBoolean(Value: Boolean);
    procedure SetAsByte(const Value: TBlobByteData);
    procedure SetAsChar(const Value: string);
    procedure SetAsClob(const Value: IIfxLob);
    procedure SetAsCurrency(Value: Currency);
    procedure SetAsDate(Value: int4);
    procedure SetAsDateTime(Value: TDateTime);
    procedure SetAsDecimal(const Value: TDecimal);
    procedure SetAsDTime(const Value: TDTime);
    procedure SetAsFloat(Value: Double);
    procedure SetAsInt8(const Value: TIfx_int8);
    procedure SetAsInteger(Value: int4);
    procedure SetAsInterval(const Value: TIntrvl);
    procedure SetAsLargeint(Value: Largeint);
    procedure SetAsLocator(Value: PLoc);
    procedure SetAsLVarChar(const Value: string);
    procedure SetAsMoney(const Value: TDecimal);
    procedure SetAsNChar(const Value: string);
    procedure SetAsNVarChar(const Value: string);
    procedure SetAsOpaque(const Value: string);
    procedure SetAsSmallFloat(Value: Single);
    procedure SetAsSmallInt(Value: int2);
    procedure SetAsSQLTimeStamp(const Value: TSQLTimeStamp);
    procedure SetAsText(const Value: string);
    procedure SetAsTime(Value: TDateTime);
    procedure SetAsVarChar(const Value: string);
    procedure SetAsVariant(const Value: Variant);

    property IsNull: Boolean read GetIsNull;
    property AsBCD: TBcd read GetAsBCD write SetAsBCD;
    property AsBlob: IIfxLob read GetAsLob write SetAsBlob;
    property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean;
    property AsByte: TBlobByteData read GetAsByte write SetAsByte;
    property AsChar: string read GetAsString write SetAsChar;
    property AsClob: IIfxLob read GetAsLob write SetAsClob;
    property AsCurrency: Currency read GetAsCurrency write SetAsCurrency;
    property AsDate: int4 read GetAsDate write SetAsDate;
    property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime;
    property AsDecimal: TDecimal read GetAsDecimal write SetAsDecimal;
    property AsDTime: TDTime read GetAsDTime write SetAsDTime;
    property AsFloat: Double read GetAsFloat write SetAsFloat;
    property AsInt8: TIfx_int8 read GetAsInt8 write SetAsInt8;
    property AsInteger: int4 read GetAsInteger write SetAsInteger;
    property AsInterval: TIntrvl read GetAsInterval write SetAsInterval;
    property AsLargeint: Largeint read GetAsLargeint write SetAsLargeint;
    property AsLob: IIfxLob read GetAsLob;
    property AsLocator: PLoc read GetAsLocator write SetAsLocator;
    property AsLVarChar: string read GetAsString write SetAsLVarChar;
    property AsMoney: TDecimal read GetAsDecimal write SetAsMoney;
    property AsNChar: string read GetAsString write SetAsNChar;
    property AsNVarChar: string read GetAsString write SetAsNVarChar;
    property AsOpaque: string read GetAsString write SetAsOpaque;
    property AsSmallFloat: Single read GetAsSmallFloat write SetAsSmallFloat;
    property AsSmallInt: int2 read GetAsSmallInt write SetAsSmallInt;
    property AsSQLTimeStamp: TSQLTimeStamp read GetAsSQLTimeStamp write SetAsSQLTimeStamp;
    property AsString: string read GetAsString write SetAsChar;
    property AsText: string read GetAsString write SetAsText;
    property AsTime: TDateTime read GetAsTime write SetAsTime;
    property AsVarChar: string read GetAsString write SetAsVarChar;
    property AsVariant: Variant read GetAsVariant write SetAsVariant;

    function Format(const FmtStr: string): string;

    procedure AssignValue(const Value: IIfxValue);
    procedure AssignToValue(const Value: IIfxValue);
  end;


{ TIfxValue }

  TIfxValue = class
  private
    procedure InvalidCast(const TypeName: string);

  protected
    function GetAsBCD: TBcd; virtual;
    function GetAsBoolean: Boolean; virtual;
    function GetAsByte: TBlobByteData; virtual;
    function GetAsCurrency: Currency; virtual;
    function GetAsDate: int4; virtual;
    function GetAsDateTime: TDateTime; virtual;
    function GetAsDecimal: TDecimal; virtual;
    function GetAsDTime: TDTime; virtual;
    function GetAsFloat: Double; virtual;
    function GetAsInt8: TIfx_int8; virtual;
    function GetAsInteger: int4; virtual;
    function GetAsInterval: TIntrvl; virtual;
    function GetAsLargeint: Largeint; virtual;
    function GetAsLob: IIfxLob; virtual;
    function GetAsLocator: PLoc; virtual;
    function GetAsSmallFloat: Single; virtual;
    function GetAsSmallInt: int2; virtual;
    function GetAsSqlTimeStamp: TSQLTimeStamp; virtual;
    function GetAsString: string; virtual;
    function GetAsTime: TDateTime; virtual;
    function GetAsVariant: Variant; virtual;

  public
    property AsBCD: TBcd read GetAsBCD;
    property AsBoolean: Boolean read GetAsBoolean;
    property AsByte: TBlobByteData read GetAsByte;
    property AsCurrency: Currency read GetAsCurrency;
    property AsDate: int4 read GetAsDate;
    property AsDateTime: TDateTime read GetAsDateTime;
    property AsDecimal: TDecimal read GetAsDecimal;
    property AsDTime: TDTime read GetAsDTime;
    property AsFloat: Double read GetAsFloat;
    property AsInt8: TIfx_int8 read GetAsInt8;
    property AsInteger: int4 read GetAsInteger;
    property AsInterval: TIntrvl read GetAsInterval;
    property AsLargeint: Largeint read GetAsLargeint;
    property AsLob: IIfxLob read GetAsLob;
    property AsLocator: PLoc read GetAsLocator;
    property AsSmallFloat: Single read GetAsSmallFloat;
    property AsSmallInt: int2 read GetAsSmallInt;
    property AsSQLTimeStamp: TSQLTimeStamp read GetAsSQLTimeStamp;
    property AsString: string read GetAsString;
    property AsTime: TDateTime read GetAsTime;
    property AsVariant: Variant read GetAsVariant;

    function Format(const FmtStr: string): string; virtual;
    
    procedure SaveToStream(Stream: TStream); virtual;
    procedure SaveToFile(const FileName: string); virtual;

    procedure AssignTo(const Dest: IIfxValue); overload; virtual; abstract;
  end;


{ TIfxNullValue }

  TIfxNullValue = class(TIfxValue)
  protected
    function GetAsBCD: TBcd; override;
    function GetAsBoolean: Boolean; override;
    function GetAsByte: TBlobByteData; override;
    function GetAsCurrency: Currency; override;
    function GetAsDate: int4; override;
    function GetAsDateTime: TDateTime; override;
    function GetAsDecimal: TDecimal; override;
    function GetAsDTime: TDTime; override;
    function GetAsFloat: Double; override;
    function GetAsInt8: TIfx_int8; override;
    function GetAsInteger: int4; override;
    function GetAsInterval: TIntrvl; override;
    function GetAsLargeint: Largeint; override;
    function GetAsLob: IIfxLob; override;
    function GetAsLocator: PLoc; override;
    function GetAsSmallFloat: Single; override;
    function GetAsSmallInt: int2; override;
    function GetAsSqlTimeStamp: TSQLTimeStamp; override;
    function GetAsString: string; override;
    function GetAsTime: TDateTime; override;
    function GetAsVariant: Variant; override;
    
  public
    class function Instance: TIfxNullValue;

    function Format(const FmtStr: string): string; override;

    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ IIfxValueBufferProvider }

  IIfxValueBufferProvider = interface
    ['{E0DDC543-73D9-4BBA-94C0-854B0D01EDBB}']

    function GetSize: Integer;
    function DataReadBuffer: PChar;
    function DataWriteBuffer: PChar;
    procedure Validate(Buffer: Pointer);
    function ResetSubject: TLXDelegat;
  end;


{ TIfxFieldValue }

  TIfxFieldValue = class(TIfxValue)
  private
    FBufferProvider: IIfxValueBufferProvider;

  protected
    function GetSize: Integer;
    function DataReadBuffer: PChar;
    function DataWriteBuffer: PChar;
    procedure Validate(Buffer: Pointer);
    function ResetSubject: TLXDelegat;

    function GetBufferSize: Integer; virtual; abstract;
    
    procedure SetAsBCD(const Value: TBcd); virtual;
    procedure SetAsBoolean(Value: Boolean); virtual;
    procedure SetAsByte(const Value: TBlobByteData); virtual;
    procedure SetAsCurrency(Value: Currency); virtual;
    procedure SetAsDate(Value: int4); virtual;
    procedure SetAsDateTime(Value: TDateTime); virtual;
    procedure SetAsDecimal(const Value: TDecimal); virtual;
    procedure SetAsDTime(const Value: TDTime); virtual;
    procedure SetAsFloat(Value: Double); virtual;
    procedure SetAsInt8(const Value: TIfx_int8); virtual;
    procedure SetAsInteger(Value: int4); virtual;
    procedure SetAsInterval(const Value: TIntrvl); virtual;
    procedure SetAsLargeint(Value: Largeint); virtual;
    procedure SetAsLob(const Value: IIfxLob); virtual;
    procedure SetAsLocator(Value: PLoc); virtual;
    procedure SetAsSmallFloat(Value: Single); virtual;
    procedure SetAsSmallInt(Value: int2); virtual;
    procedure SetAsSQLTimeStamp(const Value: TSQLTimeStamp); virtual;
    procedure SetAsString(const Value: string); virtual;
    procedure SetAsTime(Value: TDateTime); virtual;
    procedure SetAsVariant(const Value: Variant); virtual;

  public
    constructor Create(const BufferProvider: IIfxValueBufferProvider);

    procedure AllocateBuffer(var Buffer: PChar); virtual;
    procedure FreeBuffer(Buffer: PChar); virtual;

    property BufferSize: Integer read GetBufferSize;
    property AsBCD: TBcd read GetAsBCD write SetAsBCD;
    property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean;
    property AsByte: TBlobByteData read GetAsByte write SetAsByte;
    property AsCurrency: Currency read GetAsCurrency write SetAsCurrency;
    property AsDate: int4 read GetAsDate write SetAsDate;
    property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime;
    property AsDecimal: TDecimal read GetAsDecimal write SetAsDecimal;
    property AsDTime: TDTime read GetAsDTime write SetAsDTime;
    property AsFloat: Double read GetAsFloat write SetAsFloat;
    property AsInt8: TIfx_int8 read GetAsInt8 write SetAsInt8;
    property AsInteger: int4 read GetAsInteger write SetAsInteger;
    property AsInterval: TIntrvl read GetAsInterval write SetAsInterval;
    property AsLargeint: Largeint read GetAsLargeint write SetAsLargeint;
    property AsLob: IIfxLob read GetAsLob write SetAsLob;
    property AsLocator: PLoc read GetAsLocator write SetAsLocator;
    property AsSmallFloat: Single read GetAsSmallFloat write SetAsSmallFloat;
    property AsSmallInt: int2 read GetAsSmallInt write SetAsSmallInt;
    property AsSQLTimeStamp: TSQLTimeStamp read GetAsSQLTimeStamp write SetAsSQLTimeStamp;
    property AsString: string read GetAsString write SetAsString;
    property AsTime: TDateTime read GetAsTime write SetAsTime;
    property AsVariant: Variant read GetAsVariant write SetAsVariant;

    procedure SaveToStream(Stream: TStream); override;
    procedure SaveToFile(const FileName: string); override;
    procedure LoadFromStream(Stream: TStream); virtual;
    procedure LoadFromFile(const FileName: string); virtual;
  end;


{ TIfxStringValue }

  TIfxStringValue = class(TIfxFieldValue)
  private
    function GetValue: string;
    procedure SetValue(const Value: string);

  protected
    function GetBufferSize: Integer; override;

    function GetAsBCD: TBcd; override;
    function GetAsBoolean: Boolean; override;
    function GetAsCurrency: Currency; override;
    function GetAsDate: int4; override;
    function GetAsDateTime: TDateTime; override;
    function GetAsDecimal: TDecimal; override;
    function GetAsDTime: TDTime; override;
    function GetAsFloat: Double; override;
    function GetAsInt8: TIfx_int8; override;
    function GetAsInteger: int4; override;
    function GetAsInterval: TIntrvl; override;
    function GetAsLargeint: Largeint; override;
    function GetAsSmallFloat: Single; override;
    function GetAsSmallInt: int2; override;
    function GetAsTime: TDateTime; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsBCD(const Value: TBcd); override;
    procedure SetAsBoolean(Value: Boolean); override;
    procedure SetAsCurrency(Value: Currency); override;
    procedure SetAsDate(Value: int4); override;
    procedure SetAsDateTime(Value: TDateTime); override;
    procedure SetAsDecimal(const Value: TDecimal); override;
    procedure SetAsDTime(const Value: TDTime); override;
    procedure SetAsFloat(Value: Double); override;
    procedure SetAsInt8(const Value: TIfx_int8); override;
    procedure SetAsInteger(Value: int4); override;
    procedure SetAsInterval(const Value: TIntrvl); override;
    procedure SetAsLargeint(Value: Largeint); override;
    procedure SetAsSmallFloat(Value: Single); override;
    procedure SetAsSmallInt(Value: int2); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsTime(Value: TDateTime); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AllocateBuffer(var Buffer: PChar); override;
  end;


{ TIfxCharValue }

  TIfxCharValue = class(TIfxStringValue)
  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxVarCharValue }

  TIfxVarCharValue = class(TIfxStringValue)
  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxNCharValue }

  TIfxNCharValue = class(TIfxStringValue)
  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxNVarCharValue }

  TIfxNVarCharValue = class(TIfxStringValue)
  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxLVarCharValue }

  TIfxLVarCharValue = class(TIfxStringValue)
  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxSmallIntValue }

  TIfxSmallIntValue = class(TIfxFieldValue)
  private
    function GetValue: int2;
    procedure SetValue(Value: int2);

  protected
    function GetBufferSize: Integer; override;
    
    function GetAsBCD: TBcd; override;
    function GetAsCurrency: Currency; override;
    function GetAsDecimal: TDecimal; override;
    function GetAsFloat: Double; override;
    function GetAsInt8: TIfx_int8; override;
    function GetAsInteger: int4; override;
    function GetAsLargeint: Largeint; override;
    function GetAsSmallFloat: Single; override;
    function GetAsSmallInt: int2; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsBCD(const Value: TBcd); override;
    procedure SetAsCurrency(Value: Currency); override;
    procedure SetAsDecimal(const Value: TDecimal); override;
    procedure SetAsFloat(Value: Double); override;
    procedure SetAsInt8(const Value: TIfx_int8); override;
    procedure SetAsInteger(Value: int4); override;
    procedure SetAsLargeint(Value: Largeint); override;
    procedure SetAsSmallFloat(Value: Single); override;
    procedure SetAsSmallInt(Value: int2); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AssignTo(const Dest: IIfxValue); override;

    function Format(const FmtStr: string): string; override;
  end;


{ TIfxIntegerValue }

  TIfxIntegerValue = class(TIfxFieldValue)
  private
    function GetValue: int4;
    procedure SetValue(Value: int4);

  protected
    function GetBufferSize: Integer; override;
    
    function GetAsBCD: TBcd; override;
    function GetAsCurrency: Currency; override;
    function GetAsDecimal: TDecimal; override;
    function GetAsFloat: Double; override;
    function GetAsInt8: TIfx_int8; override;
    function GetAsInteger: int4; override;
    function GetAsLargeint: Largeint; override;
    function GetAsSmallFloat: Single; override;
    function GetAsSmallInt: int2; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;
    
    procedure SetAsBCD(const Value: TBcd); override;
    procedure SetAsCurrency(Value: Currency); override;
    procedure SetAsDecimal(const Value: TDecimal); override;
    procedure SetAsFloat(Value: Double); override;
    procedure SetAsInt8(const Value: TIfx_int8); override;
    procedure SetAsInteger(Value: int4); override;
    procedure SetAsLargeint(Value: Largeint); override;
    procedure SetAsSmallFloat(Value: Single); override;
    procedure SetAsSmallInt(Value: int2); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AssignTo(const Dest: IIfxValue); override;

    function Format(const FmtStr: string): string; override;
  end;


{ TIfxFloatValue }

  TIfxFloatValue = class(TIfxFieldValue)
  private
    function GetValue: Double;
    procedure SetValue(Value: Double);

  protected
    function GetBufferSize: Integer; override;
    
    function GetAsBCD: TBcd; override;
    function GetAsCurrency: Currency; override;
    function GetAsDecimal: TDecimal; override;
    function GetAsFloat: Double; override;
    function GetAsInt8: TIfx_int8; override;
    function GetAsInteger: int4; override;
    function GetAsLargeint: Largeint; override;
    function GetAsSmallFloat: Single; override;
    function GetAsSmallInt: int2; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsBCD(const Value: TBcd); override;
    procedure SetAsCurrency(Value: Currency); override;
    procedure SetAsDecimal(const Value: TDecimal); override;
    procedure SetAsFloat(Value: Double); override;
    procedure SetAsInt8(const Value: TIfx_int8); override;
    procedure SetAsInteger(Value: int4); override;
    procedure SetAsLargeint(Value: Largeint); override;
    procedure SetAsSmallFloat(Value: Single); override;
    procedure SetAsSmallInt(Value: int2); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AssignTo(const Dest: IIfxValue); override;

    function Format(const FmtStr: string): string; override;
  end;


{ TIfxSmallFloatValue }

  TIfxSmallFloatValue = class(TIfxFieldValue)
  private
    function GetValue: Single;
    procedure SetValue(Value: Single);

  protected
    function GetBufferSize: Integer; override;

    function GetAsBCD: TBcd; override;
    function GetAsCurrency: Currency; override;
    function GetAsDecimal: TDecimal; override;
    function GetAsFloat: Double; override;
    function GetAsInt8: TIfx_int8; override;
    function GetAsInteger: int4; override;
    function GetAsLargeint: Largeint; override;
    function GetAsSmallFloat: Single; override;
    function GetAsSmallInt: int2; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsBCD(const Value: TBcd); override;
    procedure SetAsCurrency(Value: Currency); override;
    procedure SetAsDecimal(const Value: TDecimal); override;
    procedure SetAsFloat(Value: Double); override;
    procedure SetAsInt8(const Value: TIfx_int8); override;
    procedure SetAsInteger(Value: int4); override;
    procedure SetAsLargeint(Value: Largeint); override;
    procedure SetAsSmallFloat(Value: Single); override;
    procedure SetAsSmallInt(Value: int2); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AssignTo(const Dest: IIfxValue); override;

    function Format(const FmtStr: string): string; override;
  end;


{ TIfxDecimalValue }

  TIfxDecimalValue = class(TIfxFieldValue)
  private
    function GetValue: PDecimal;
    procedure SetValue(const Value: TDecimal);

  protected
    function GetBufferSize: Integer; override;

    function GetAsBCD: TBcd; override;
    function GetAsCurrency: Currency; override;
    function GetAsDecimal: TDecimal; override;
    function GetAsFloat: Double; override;
    function GetAsInt8: TIfx_int8; override;
    function GetAsInteger: int4; override;
    function GetAsLargeint: Largeint; override;
    function GetAsSmallFloat: Single; override;
    function GetAsSmallInt: int2; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsBCD(const Value: TBcd); override;
    procedure SetAsCurrency(Value: Currency); override;
    procedure SetAsDecimal(const Value: TDecimal); override;
    procedure SetAsFloat(Value: Double); override;
    procedure SetAsInt8(const Value: TIfx_int8); override;
    procedure SetAsInteger(Value: int4); override;
    procedure SetAsLargeint(Value: Largeint); override;
    procedure SetAsSmallFloat(Value: Single); override;
    procedure SetAsSmallInt(Value: int2); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    function Format(const FmtStr: string): string; override;

    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxMoneyValue }

  TIfxMoneyValue = class(TIfxDecimalValue)
  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxDateValue }

  TIfxDateValue = class(TIfxFieldValue)
  private
    function GetValue: int4;
    procedure SetValue(Value: int4);

  protected
    function GetBufferSize: Integer; override;

    function GetAsDate: int4; override;
    function GetAsDateTime: TDateTime; override;
    function GetAsDTime: TDTime; override;
    function GetAsSqlTimeStamp: TSQLTimeStamp; override;
    function GetAsString: string; override;
    function GetAsTime: TDateTime; override;
    function GetAsVariant: Variant; override;

    procedure SetAsDate(Value: int4); override;
    procedure SetAsDateTime(Value: TDateTime); override;
    procedure SetAsDTime(const Value: TDTime); override;
    procedure SetAsSQLTimeStamp(const Value: TSQLTimeStamp); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsTime(Value: TDateTime); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AssignTo(const Dest: IIfxValue); override;

    function Format(const FmtStr: string): string; override;
  end;


{ TIfxDTimeValue }

  TIfxDTimeValue = class(TIfxFieldValue)
  private
    function GetValue: PDTime;
    procedure SetValue(const Value: TDTime);

  protected
    function GetBufferSize: Integer; override;

    function GetAsDate: int4; override;
    function GetAsDateTime: TDateTime; override;
    function GetAsDTime: TDTime; override;
    function GetAsSqlTimeStamp: TSQLTimeStamp; override;
    function GetAsString: string; override;
    function GetAsTime: TDateTime; override;
    function GetAsVariant: Variant; override;

    procedure SetAsDate(Value: int4); override;
    procedure SetAsDateTime(Value: TDateTime); override;
    procedure SetAsDTime(const Value: TDTime); override;
    procedure SetAsSQLTimeStamp(const Value: TSQLTimeStamp); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsTime(Value: TDateTime); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AssignTo(const Dest: IIfxValue); override;

    function Format(const FmtStr: string): string; override;
  end;


{ TIfxLocatorValue }

  TIfxLocatorValue = class(TIfxFieldValue)
  private
    function GetValue: PLoc;

  protected
    function GetBufferSize: Integer; override;

    function GetAsByte: TBlobByteData; override;
    function GetAsLocator: PLoc; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsByte(const Value: TBlobByteData); override;
    procedure SetAsLocator(Value: PLoc); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure SetTypedValue(sqltype: int2; Size: Integer; Data: Pointer);
    
    procedure AllocateBuffer(var Buffer: PChar); override;
    procedure FreeBuffer(Buffer: PChar); override;

    procedure SaveToStream(Stream: TStream); override;
    procedure LoadFromStream(Stream: TStream); override;

    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxIntervalValue }

  TIfxIntervalValue = class(TIfxFieldValue)
  private
    function GetValue: PIntrvl;
    procedure SetValue(const Value: TIntrvl);

  protected
    function GetBufferSize: Integer; override;

    function GetAsInterval: TIntrvl; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsInterval(const Value: TIntrvl); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AssignTo(const Dest: IIfxValue); override;

    function Format(const FmtStr: string): string; override;
  end;


{ TIfxInt8Value }

  TIfxInt8Value = class(TIfxFieldValue)
  private
    function GetValue: PIfx_int8;
    procedure SetValue(const Value: TIfx_int8);

  protected
    function GetBufferSize: Integer; override;

    function GetAsBCD: TBcd; override;
    function GetAsCurrency: Currency; override;
    function GetAsDecimal: TDecimal; override;
    function GetAsFloat: Double; override;
    function GetAsInt8: TIfx_int8; override;
    function GetAsInteger: int4; override;
    function GetAsLargeint: Largeint; override;
    function GetAsSmallFloat: Single; override;
    function GetAsSmallInt: int2; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsBCD(const Value: TBcd); override;
    procedure SetAsCurrency(Value: Currency); override;
    procedure SetAsDecimal(const Value: TDecimal); override;
    procedure SetAsFloat(Value: Double); override;
    procedure SetAsInt8(const Value: TIfx_int8); override;
    procedure SetAsInteger(Value: int4); override;
    procedure SetAsLargeint(Value: Largeint); override;
    procedure SetAsSmallFloat(Value: Single); override;
    procedure SetAsSmallInt(Value: int2); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxOpaqueValue }

  TIfxOpaqueValue = class(TIfxFieldValue)
  private
    FAllocFlag: mint;
    FAttached: Boolean;

    function GetValue: string;
    procedure SetValue(const Value: string);

    procedure ResetBuffer(Args: TObject);

  protected
    function GetBufferSize: Integer; override;

    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    class function IsEnabled: Boolean;

    constructor Create(const BufferProvider: IIfxValueBufferProvider; AllocFlag: mint);

    procedure AllocateBuffer(var Buffer: PChar); override;
    procedure FreeBuffer(Buffer: PChar); override;

    procedure SaveToStream(Stream: TStream); override;
    procedure LoadFromStream(Stream: TStream); override;

    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxLobBufferStrategy }

  TIfxLobBufferStrategy = class
  private
    FConnProvider: IIfxConnectionProvider;

    function GetConnection: TIfxConnection;
    procedure SetAsBuffer(Buffer: PChar; Size: Integer; Data: PChar);

  public
    constructor Create(const ConnProvider: IIfxConnectionProvider);

    function GetBufferSize: Integer; virtual;
    procedure Copy(Source, Dest: PChar); virtual;

    function RequiresCleanup: Boolean; virtual;
    procedure Cleanup(Buffer: PChar); virtual;

    function GetAsByte(Buffer: PChar): TBlobByteData; virtual;
    function GetAsLob(Buffer: PChar): IIfxLob; virtual;
    function GetAsString(Buffer: PChar): string; virtual;

    procedure SetAsByte(Buffer: PChar; const Value: TBlobByteData); virtual;
    procedure SetAsLob(Buffer: PChar; const Value: IIfxLob); virtual;
    procedure SetAsLocator(Buffer: PChar; Value: PLoc); virtual;
    procedure SetAsString(Buffer: PChar; const Value: string); virtual;

    procedure SaveToStream(Buffer: PChar; Stream: TStream); virtual;
    procedure LoadFromStream(Buffer: PChar; Stream: TStream); virtual;
    function CreateReadingStream(Buffer: PChar): TStream; virtual;

    property Connection: TIfxConnection read GetConnection;
  end;


{ TIfxLobValue }

  TIfxLobValue = class(TIfxFieldValue)
  private
    FBufferStrategy: TIfxLobBufferStrategy;

  protected
    function GetBufferSize: Integer; override;

    function GetAsByte: TBlobByteData; override;
    function GetAsLob: IIfxLob; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsByte(const Value: TBlobByteData); override;
    procedure SetAsLob(const Value: IIfxLob); override;
    procedure SetAsLocator(Value: PLoc); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    constructor Create(const BufferProvider: IIfxValueBufferProvider;
      BufferStrategy: TIfxLobBufferStrategy);

    procedure FreeBuffer(Buffer: PChar); override;
    
    procedure SaveToStream(Stream: TStream); override;
    procedure LoadFromStream(Stream: TStream); override;
  end;


{ TIfxBlobValue }

  TIfxBlobValue = class(TIfxLobValue)
  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;


{ TIfxClobValue }

  TIfxClobValue = class(TIfxLobValue)
  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;

  
{ TIfxBooleanValue }

  TIfxBooleanValue = class(TIfxFieldValue)
  private
    function GetValue: Boolean;
    procedure SetValue(Value: Boolean);

  protected
    function GetBufferSize: Integer; override;

    function GetAsBoolean: Boolean; override;
    function GetAsString: string; override;
    function GetAsVariant: Variant; override;

    procedure SetAsBoolean(Value: Boolean); override;
    procedure SetAsString(const Value: string); override;
    procedure SetAsVariant(const Value: Variant); override;

  public
    procedure AssignTo(const Dest: IIfxValue); override;
  end;


implementation

uses SysUtils, LXTypes, LXSysUtils, LXVariants, IfxSqlTypes, IfxSqlHdr,
  IfxConsts, Ifx, IfxIntf, IfxConvert;


{ TIfxValue }

procedure TIfxValue.InvalidCast(const TypeName: string);
begin
  IDACErrorFmt(SInvalidConversion, [TypeName]);
end;

function TIfxValue.GetAsBCD: TBcd;
begin
  InvalidCast('BCD');
end;

function TIfxValue.GetAsBoolean: Boolean;
begin
  InvalidCast('Boolean');
end;

function TIfxValue.GetAsByte: TBlobByteData;
begin
  InvalidCast('Byte');
end;

function TIfxValue.GetAsCurrency: Currency;
begin
  InvalidCast('Currencty');
end;

function TIfxValue.GetAsDate: int4;
begin
  InvalidCast('Date');
end;

function TIfxValue.GetAsDateTime: TDateTime;
begin
  InvalidCast('DateTime');
end;

function TIfxValue.GetAsDecimal: TDecimal;
begin
  InvalidCast('Decimal');
end;

function TIfxValue.GetAsDTime: TDTime;
begin
  InvalidCast('DTime');
end;

function TIfxValue.GetAsFloat: Double;
begin
  InvalidCast('Float');
end;

function TIfxValue.GetAsInt8: TIfx_int8;
begin
  InvalidCast('Int8');
end;

function TIfxValue.GetAsInteger: int4;
begin
  InvalidCast('Integer');
end;

function TIfxValue.GetAsInterval: TIntrvl;
begin
  InvalidCast('Interval');
end;

function TIfxValue.GetAsLargeint: Largeint;
begin
  InvalidCast('Largeint');
end;

function TIfxValue.GetAsLob: IIfxLob;
begin
  InvalidCast('Blob/Clob');
end;

function TIfxValue.GetAsLocator: PLoc;
begin
  InvalidCast('Locator');
end;

function TIfxValue.GetAsSmallFloat: Single;
begin
  InvalidCast('SmallFloat');
end;

function TIfxValue.GetAsSmallInt: int2;
begin
  InvalidCast('SmallInt');
end;

function TIfxValue.GetAsSqlTimeStamp: TSQLTimeStamp;
begin
  InvalidCast('SqlTimeStamp');
end;

function TIfxValue.GetAsString: string;
begin
  InvalidCast('String');
end;

function TIfxValue.GetAsTime: TDateTime;
begin
  InvalidCast('Time');
end;

function TIfxValue.GetAsVariant: Variant;
begin
  InvalidCast('Variant');
end;

function TIfxValue.Format(const FmtStr: string): string;
begin
  InvalidCast('Format');
end;

procedure TIfxValue.SaveToStream(Stream: TStream);
begin
  InvalidCast('Stream');
end;

procedure TIfxValue.SaveToFile(const FileName: string);
begin
  InvalidCast('File');
end;


{ TIfxNullValue }

var
  globalNullValue: TIfxNullValue;

class function TIfxNullValue.Instance: TIfxNullValue;
begin
  Result := globalNullValue;
end;

function TIfxNullValue.GetAsBCD: TBcd;
begin
  FillChar(Result, SizeOf(Result), 0);
end;

function TIfxNullValue.GetAsByte: TBlobByteData;
begin
  Result := nil;
end;

function TIfxNullValue.GetAsBoolean: Boolean;
begin
  Result := False;
end;

function TIfxNullValue.GetAsCurrency: Currency;
begin
  Result := 0;
end;

function TIfxNullValue.GetAsDate: int4;
begin
  Result := 0;
end;

function TIfxNullValue.GetAsDateTime: TDateTime;
begin
  Result := 0;
end;

function TIfxNullValue.GetAsDecimal: TDecimal;
begin
  FillChar(Result, SizeOf(Result), 0);
  Result.dec_pos := -1;
end;

function TIfxNullValue.GetAsFloat: Double;
begin
  Result := 0;
end;

function TIfxNullValue.GetAsDTime: TDTime;
begin
  FillChar(Result, SizeOf(Result), 0);
  Result.dt_dec.dec_pos := -1;
end;

function TIfxNullValue.GetAsLargeint: Largeint;
begin
  Result := 0;
end;

function TIfxNullValue.GetAsLob: IIfxLob;
begin
  Result := nil;
end;

function TIfxNullValue.GetAsInt8: TIfx_int8;
begin
  FillChar(Result, SizeOf(Result), 0);
end;

function TIfxNullValue.GetAsInteger: int4;
begin
  Result := 0;
end;

function TIfxNullValue.GetAsInterval: Intrvl;
begin
  FillChar(Result, SizeOf(Result), 0);
  Result.in_dec.dec_pos := -1;
end;

function TIfxNullValue.GetAsLocator: PLoc;
begin
  Result := nil;
end;

function TIfxNullValue.GetAsSmallFloat: Single;
begin
  Result := 0;
end;

function TIfxNullValue.GetAsSmallInt: int2;
begin
  Result := 0;
end;

function TIfxNullValue.GetAsSqlTimeStamp: TSQLTimeStamp;
begin
  FillChar(Result, SizeOf(Result), 0);
end;

function TIfxNullValue.GetAsString: string;
begin
  Result := '';
end;

function TIfxNullValue.GetAsTime: TDateTime;
begin
  Result := 0;
end;

function TIfxNullValue.GetAsVariant: Variant;
begin
  Result := LXNull;
end;

function TIfxNullValue.Format(const FmtStr: string): string;
begin
  Result := '';
end;

procedure TIfxNullValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetNull;
end;


{ TIfxFieldValue }

constructor TIfxFieldValue.Create(const BufferProvider: IIfxValueBufferProvider);
begin
  FBufferProvider := BufferProvider;
end;

procedure TIfxFieldValue.AllocateBuffer(var Buffer: PChar);
begin
  Buffer := AllocMem(BufferSize);
end;

procedure TIfxFieldValue.FreeBuffer(Buffer: PChar);
begin
  FreeMem(Buffer);
end;

function TIfxFieldValue.GetSize: Integer;
begin
  Result := FBufferProvider.GetSize;
end;

function TIfxFieldValue.DataReadBuffer: PChar;
begin
  Result := FBufferProvider.DataReadBuffer;
end;

function TIfxFieldValue.DataWriteBuffer: PChar;
begin
  Result := FBufferProvider.DataWriteBuffer;
end;

procedure TIfxFieldValue.Validate(Buffer: Pointer);
begin
  FBufferProvider.Validate(Buffer);
end;

function TIfxFieldValue.ResetSubject: TLXDelegat;
begin
  Result := FBufferProvider.ResetSubject;
end;

procedure TIfxFieldValue.SetAsBCD(const Value: TBcd);
begin
  InvalidCast('BCD');
end;

procedure TIfxFieldValue.SetAsByte(const Value: TBlobByteData);
begin
  InvalidCast('Byte');
end;

procedure TIfxFieldValue.SetAsBoolean(Value: Boolean);
begin
  InvalidCast('Boolean');
end;

procedure TIfxFieldValue.SetAsCurrency(Value: Currency);
begin
  InvalidCast('Currency');
end;

procedure TIfxFieldValue.SetAsDate(Value: int4);
begin
  InvalidCast('Date');
end;

procedure TIfxFieldValue.SetAsDateTime(Value: TDateTime);
begin
  InvalidCast('DateTime');
end;

procedure TIfxFieldValue.SetAsDecimal(const Value: TDecimal);
begin
  InvalidCast('Decimal');
end;

procedure TIfxFieldValue.SetAsDTime(const Value: TDTime);
begin
  InvalidCast('DTime');
end;

procedure TIfxFieldValue.SetAsFloat(Value: Double);
begin
  InvalidCast('Float');
end;

procedure TIfxFieldValue.SetAsInt8(const Value: TIfx_int8);
begin
  InvalidCast('Int8');
end;

procedure TIfxFieldValue.SetAsInteger(Value: int4);
begin
  InvalidCast('Integer');
end;

procedure TIfxFieldValue.SetAsInterval(const Value: TIntrvl);
begin
  InvalidCast('Interval');
end;

procedure TIfxFieldValue.SetAsLargeint(Value: Largeint);
begin
  InvalidCast('Largeint');
end;

procedure TIfxFieldValue.SetAsLob(const Value: IIfxLob);
begin
  InvalidCast('Blob/Clob');
end;

procedure TIfxFieldValue.SetAsLocator(Value: PLoc);
begin
  InvalidCast('Locator');
end;

procedure TIfxFieldValue.SetAsSmallFloat(Value: Single);
begin
  InvalidCast('SmallFloat');
end;

procedure TIfxFieldValue.SetAsSmallInt(Value: int2);
begin
  InvalidCast('SmallInt');
end;

procedure TIfxFieldValue.SetAsSQLTimeStamp(const Value: TSQLTimeStamp);
begin
  InvalidCast('SQLTimeStamp');
end;

procedure TIfxFieldValue.SetAsString(const Value: string);
begin
  InvalidCast('String');
end;

procedure TIfxFieldValue.SetAsTime(Value: TDateTime);
begin
  InvalidCast('Time');
end;

procedure TIfxFieldValue.SetAsVariant(const Value: Variant);
begin
  InvalidCast('Variant');
end;

procedure TIfxFieldValue.SaveToStream(Stream: TStream);
begin
  Stream.Write(DataReadBuffer^, GetSize);
end;

procedure TIfxFieldValue.SaveToFile(const FileName: string);
var
  Stream: TStream;
begin
  Stream := TFileStream.Create(FileName, fmCreate);
  try
    SaveToStream(Stream);
  finally
    Stream.Free;
  end;
end;

procedure TIfxFieldValue.LoadFromStream(Stream: TStream);
begin
  Stream.ReadBuffer(DataWriteBuffer^, GetSize);
end;

procedure TIfxFieldValue.LoadFromFile(const FileName: string);
var
  Stream: TStream;
begin
  Stream := TFileStream.Create(FileName, fmOpenRead);
  try
    LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;


{ TIfxStringValue }

procedure TIfxStringValue.AllocateBuffer(var Buffer: PChar);
begin
  GetMem(Buffer, BufferSize + 1);
end;

function TIfxStringValue.GetValue: string;
var
  P: PChar;
begin
  P := DataReadBuffer;
  SetString(Result, P, StrLen(P));
end;

procedure TIfxStringValue.SetValue(const Value: string);
begin
  Validate(PChar(Value));
  LXStrPLCopy(DataWriteBuffer, Value, GetSize);
end;

function TIfxStringValue.GetBufferSize: Integer;
begin
  Result := GetSize;
end;

function TIfxStringValue.GetAsBCD: TBcd;
begin
  LXStrToBcd(GetValue, Result);
end;

function TIfxStringValue.GetAsBoolean: Boolean;
begin
  Result := GetValue = 't';
end;

function TIfxStringValue.GetAsCurrency: Currency;
begin
  Result := StrToCurr(GetValue);
end;

function TIfxStringValue.GetAsDate: int4;
begin
  Result := StringToDate(GetValue);
end;

function TIfxStringValue.GetAsDateTime: TDateTime;
begin
  Result := StrToDateTime(GetValue);
end;

function TIfxStringValue.GetAsDecimal: TDecimal;
begin
  Result := StringToDecimal(GetValue);
end;

function TIfxStringValue.GetAsDTime: TDTime;
begin
  Result := StringToDTime(GetValue, TU_ENCODE(19, TU_YEAR, TU_F5));
end;

function TIfxStringValue.GetAsFloat: Double;
begin
  Result := StringToFloat(GetValue);
end;

function TIfxStringValue.GetAsInt8: TIfx_int8;
begin
  Result := StringToInt8(GetValue);
end;

function TIfxStringValue.GetAsInteger: int4;
begin
  Result := StringToInt(GetValue);
end;

function TIfxStringValue.GetAsInterval: TIntrvl;
begin
  Result := StringToInterval(GetValue, TU_IENCODE(12, TU_DAY, TU_F3));
end;

function TIfxStringValue.GetAsLargeint: Largeint;
begin
  Result := StrToInt64(GetValue);
end;

function TIfxStringValue.GetAsSmallFloat: Single;
begin
  Result := StringToFloat(GetValue);
end;

function TIfxStringValue.GetAsSmallInt: int2;
begin
  Result := StringToSmallInt(GetValue);
end;

function TIfxStringValue.GetAsTime: TDateTime;
begin
  Result := StrToTime(GetValue);
end;

function TIfxStringValue.GetAsString: string;
begin
  Result := GetValue;
end;

function TIfxStringValue.GetAsVariant: Variant;
begin
  Result := GetValue;
end;

procedure TIfxStringValue.SetAsBCD(const Value: TBcd);
begin
  SetValue(LXBcdToStr(Value));
end;

procedure TIfxStringValue.SetAsBoolean(Value: Boolean);
begin
  if Value then SetValue('t') else SetValue('f');
end;

procedure TIfxStringValue.SetAsCurrency(Value: Currency);
begin
  SetValue(CurrToStr(Value));
end;

procedure TIfxStringValue.SetAsDate(Value: int4);
begin
  SetValue(DateToString(Value));
end;

procedure TIfxStringValue.SetAsDateTime(Value: TDateTime);
begin
  SetValue(DateTimeToStr(Value));
end;

procedure TIfxStringValue.SetAsDecimal(const Value: TDecimal);
begin
  SetValue(DecimalToString(Value));
end;

procedure TIfxStringValue.SetAsDTime(const Value: TDTime);
begin
  SetValue(DTimeToString(Value));
end;

procedure TIfxStringValue.SetAsFloat(Value: Double);
begin
  SetValue(FloatToString(Value));
end;

procedure TIfxStringValue.SetAsInt8(const Value: TIfx_int8);
begin
  SetValue(Int8ToString(Value));
end;

procedure TIfxStringValue.SetAsInteger(Value: int4);
begin
  SetValue(IntToStr(Value));
end;

procedure TIfxStringValue.SetAsInterval(const Value: TIntrvl);
begin
  SetValue(IntervalToString(Value));
end;

procedure TIfxStringValue.SetAsLargeint(Value: Largeint);
begin
  SetValue(IntToStr(Value));
end;

procedure TIfxStringValue.SetAsSmallFloat(Value: Single);
begin
  SetValue(FloatToString(Value));
end;

procedure TIfxStringValue.SetAsSmallInt(Value: int2);
begin
  SetValue(IntToStr(Value));
end;

procedure TIfxStringValue.SetAsString(const Value: string);
begin
  SetValue(Value);
end;

procedure TIfxStringValue.SetAsTime(Value: TDateTime);
begin
  SetValue(TimeToStr(Value));
end;

procedure TIfxStringValue.SetAsVariant(const Value: Variant);
begin
  SetValue(LXVarToStr(Value));
end;


{ TIfxCharValue }

procedure TIfxCharValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsChar(GetValue);
end;


{ TIfxVarCharValue }

procedure TIfxVarCharValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsVarChar(GetValue);
end;


{ TIfxNCharValue }

procedure TIfxNCharValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsNChar(GetValue);
end;


{ TIfxNVarCharValue }

procedure TIfxNVarCharValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsNVarChar(GetValue);
end;


{ TIfxLVarCharValue }

procedure TIfxLVarCharValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsLVarChar(GetValue);
end;


{ TIfxSmallIntValue }

function TIfxSmallIntValue.GetValue: int2;
begin
  Result := PInt2(DataReadBuffer)^;
end;

procedure TIfxSmallIntValue.SetValue(Value: int2);
begin
  Validate(@Value);
  PInt2(DataWriteBuffer)^ := Value;
end;

function TIfxSmallIntValue.GetBufferSize: Integer;
begin
  Result := SizeOf(int2);
end;

function TIfxSmallIntValue.GetAsBCD: TBcd;
begin
  LXIntegerToBcd(GetValue, Result);
end;

function TIfxSmallIntValue.GetAsCurrency: Currency;
begin
  Result := GetValue;
end;

function TIfxSmallIntValue.GetAsDecimal: TDecimal;
begin
  Result := SmallIntToDecimal(GetValue);
end;

function TIfxSmallIntValue.GetAsFloat: Double;
begin
  Result := GetValue;
end;

function TIfxSmallIntValue.GetAsInt8: TIfx_int8;
begin
  Result := SmallIntToInt8(GetValue);
end;

function TIfxSmallIntValue.GetAsInteger: int4;
begin
  Result := GetValue;
end;

function TIfxSmallIntValue.GetAsLargeint: Largeint;
begin
  Result := GetValue;
end;

function TIfxSmallIntValue.GetAsSmallFloat: Single;
begin
  Result := GetValue;
end;

function TIfxSmallIntValue.GetAsSmallInt: int2;
begin
  Result := GetValue;
end;

function TIfxSmallIntValue.GetAsString: string;
begin
  Result := IntToStr(GetValue);
end;

function TIfxSmallIntValue.GetAsVariant: Variant;
begin
  Result := GetValue;
end;

procedure TIfxSmallIntValue.SetAsBCD(const Value: TBcd);
begin
  SetValue(LXBcdToInteger(Value));
end;

procedure TIfxSmallIntValue.SetAsCurrency(Value: Currency);
begin
  SetValue(Round(Value));
end;

procedure TIfxSmallIntValue.SetAsDecimal(const Value: TDecimal);
begin
  SetValue(DecimalToSmallInt(Value));
end;

procedure TIfxSmallIntValue.SetAsFloat(Value: Double);
begin
  SetValue(Round(Value));
end;

procedure TIfxSmallIntValue.SetAsInt8(const Value: TIfx_int8);
begin
  SetValue(Int8ToSmallInt(Value));
end;

procedure TIfxSmallIntValue.SetAsInteger(Value: int4);
begin
  SetValue(Value);
end;

procedure TIfxSmallIntValue.SetAsLargeint(Value: Largeint);
begin
  SetValue(Value);
end;

procedure TIfxSmallIntValue.SetAsSmallFloat(Value: Single);
begin
  SetValue(Round(Value));
end;

procedure TIfxSmallIntValue.SetAsSmallInt(Value: int2);
begin
  SetValue(Value);
end;

procedure TIfxSmallIntValue.SetAsString(const Value: string);
begin
  SetValue(StringToSmallInt(Value));
end;

procedure TIfxSmallIntValue.SetAsVariant(const Value: Variant);
begin
  SetValue(Value);
end;

function TIfxSmallIntValue.Format(const FmtStr: string): string;
begin
  Result := IntToStringFmt(GetValue, FmtStr);
end;

procedure TIfxSmallIntValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsSmallInt(GetValue);
end;


{ TIfxIntegerValue }

function TIfxIntegerValue.GetValue: int4;
begin
  Result := PInt4(DataReadBuffer)^;
end;

procedure TIfxIntegerValue.SetValue(Value: int4);
begin
  Validate(@Value);
  PInt4(DataWriteBuffer)^ := Value;
end;

function TIfxIntegerValue.GetBufferSize: Integer;
begin
  Result := SizeOf(int4);
end;

function TIfxIntegerValue.GetAsBCD: TBcd;
begin
  LXIntegerToBcd(GetValue, Result);
end;

function TIfxIntegerValue.GetAsCurrency: Currency;
begin
  Result := GetValue;
end;

function TIfxIntegerValue.GetAsDecimal: TDecimal;
begin
  Result := IntToDecimal(GetValue);
end;

function TIfxIntegerValue.GetAsFloat: Double;
begin
  Result := GetValue;
end;

function TIfxIntegerValue.GetAsInt8: TIfx_int8;
begin
  Result := IntToInt8(GetValue);
end;

function TIfxIntegerValue.GetAsInteger: int4;
begin
  Result := GetValue;
end;

function TIfxIntegerValue.GetAsLargeint: Largeint;
begin
  Result := GetValue;
end;

function TIfxIntegerValue.GetAsSmallFloat: Single;
begin
  Result := GetValue;
end;

function TIfxIntegerValue.GetAsSmallInt: int2;
begin
  Result := GetValue;
end;

function TIfxIntegerValue.GetAsString: string;
begin
  Result := IntToStr(GetValue);
end;

function TIfxIntegerValue.GetAsVariant: Variant;
begin
  Result := GetValue;
end;

procedure TIfxIntegerValue.SetAsBCD(const Value: TBcd);
begin
  SetValue(LXBcdToInteger(Value));
end;

procedure TIfxIntegerValue.SetAsCurrency(Value: Currency);
begin
  SetValue(Round(Value));
end;

procedure TIfxIntegerValue.SetAsDecimal(const Value: TDecimal);
begin
  SetValue(DecimalToInt(Value));
end;

procedure TIfxIntegerValue.SetAsFloat(Value: Double);
begin
  SetValue(Round(Value));
end;

procedure TIfxIntegerValue.SetAsInt8(const Value: TIfx_int8);
begin
  SetValue(Int8ToInt(Value));
end;

procedure TIfxIntegerValue.SetAsInteger(Value: int4);
begin
  SetValue(Value);
end;

procedure TIfxIntegerValue.SetAsLargeint(Value: Largeint);
begin
  SetValue(Value);
end;

procedure TIfxIntegerValue.SetAsSmallFloat(Value: Single);
begin
  SetValue(Round(Value));
end;

procedure TIfxIntegerValue.SetAsSmallInt(Value: int2);
begin
  SetValue(Value);
end;

procedure TIfxIntegerValue.SetAsString(const Value: string);
begin
  SetValue(StringToInt(Value));
end;

procedure TIfxIntegerValue.SetAsVariant(const Value: Variant);
begin
  SetValue(Value);
end;

function TIfxIntegerValue.Format(const FmtStr: string): string;
begin
  Result := IntToStringFmt(GetValue, FmtStr);
end;

procedure TIfxIntegerValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsInteger(GetValue);
end;


{ TIfxFloatValue }

function TIfxFloatValue.GetValue: Double;
begin
  Result := PDouble(DataReadBuffer)^;
end;

procedure TIfxFloatValue.SetValue(Value: Double);
begin
  Validate(@Value);
  PDouble(DataWriteBuffer)^ := Value;
end;

function TIfxFloatValue.GetBufferSize: Integer;
begin
  Result := SizeOf(Double);
end;

function TIfxFloatValue.GetAsBCD: TBcd;
begin
  LXDoubleToBcd(GetValue, Result);
end;

function TIfxFloatValue.GetAsCurrency: Currency;
begin
  Result := GetValue;
end;

function TIfxFloatValue.GetAsDecimal: TDecimal;
begin
  Result := FloatToDecimal(GetValue);
end;

function TIfxFloatValue.GetAsFloat: Double;
begin
  Result := GetValue;
end;

function TIfxFloatValue.GetAsInt8: TIfx_int8;
begin
  Result := FloatToInt8(GetValue);
end;

function TIfxFloatValue.GetAsInteger: int4;
begin
  Result := Round(GetValue);
end;

function TIfxFloatValue.GetAsLargeint: Largeint;
begin
  Result := Round(GetValue);
end;

function TIfxFloatValue.GetAsSmallFloat: Single;
begin
  Result := GetValue;
end;

function TIfxFloatValue.GetAsSmallInt: int2;
begin
  Result := Round(GetValue);
end;

function TIfxFloatValue.GetAsString: string;
begin
  Result := FloatToString(GetValue);
end;

function TIfxFloatValue.GetAsVariant: Variant;
begin
  Result := GetValue;
end;

procedure TIfxFloatValue.SetAsBCD(const Value: TBcd);
begin
  SetValue(LXBcdToDouble(Value));
end;

procedure TIfxFloatValue.SetAsCurrency(Value: Currency);
begin
  SetValue(Value);
end;

procedure TIfxFloatValue.SetAsDecimal(const Value: TDecimal);
begin
  SetValue(DecimalToFloat(Value));
end;

procedure TIfxFloatValue.SetAsFloat(Value: Double);
begin
  SetValue(Value);
end;

procedure TIfxFloatValue.SetAsInt8(const Value: TIfx_int8);
begin
  SetValue(Int8ToFloat(Value));
end;

procedure TIfxFloatValue.SetAsInteger(Value: int4);
begin
  SetValue(Value);
end;

procedure TIfxFloatValue.SetAsLargeint(Value: Largeint);
begin
  SetValue(Value);
end;

procedure TIfxFloatValue.SetAsSmallFloat(Value: Single);
begin
  SetValue(Value);
end;

procedure TIfxFloatValue.SetAsSmallInt(Value: int2);
begin
  SetValue(Value);
end;

procedure TIfxFloatValue.SetAsString(const Value: string);
begin
  SetValue(StringToFloat(Value));
end;

procedure TIfxFloatValue.SetAsVariant(const Value: Variant);
begin
  SetValue(Value);
end;

function TIfxFloatValue.Format(const FmtStr: string): string;
begin
  Result := FloatToStringFmt(GetValue, FmtStr);
end;

procedure TIfxFloatValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsFloat(GetValue);
end;


{ TIfxSmallFloatValue }

function TIfxSmallFloatValue.GetValue: Single;
begin
  Result := PSingle(DataReadBuffer)^;
end;

procedure TIfxSmallFloatValue.SetValue(Value: Single);
begin
  Validate(@Value);
  PSingle(DataWriteBuffer)^ := Value;
end;

function TIfxSmallFloatValue.GetBufferSize: Integer;
begin
  Result := SizeOf(Single);
end;

function TIfxSmallFloatValue.GetAsBCD: TBcd;
begin
  LXDoubleToBcd(GetValue, Result);
end;

function TIfxSmallFloatValue.GetAsCurrency: Currency;
begin
  Result := GetValue;
end;

function TIfxSmallFloatValue.GetAsDecimal: TDecimal;
begin
  Result := FloatToDecimal(GetValue);
end;

function TIfxSmallFloatValue.GetAsFloat: Double;
begin
  Result := GetValue;
end;

function TIfxSmallFloatValue.GetAsInt8: TIfx_int8;
begin
  Result := SmallFloatToInt8(GetValue);
end;

function TIfxSmallFloatValue.GetAsInteger: int4;
begin
  Result := Round(GetValue);
end;

function TIfxSmallFloatValue.GetAsLargeint: Largeint;
begin
  Result := Round(GetValue);
end;

function TIfxSmallFloatValue.GetAsSmallFloat: Single;
begin
  Result := GetValue;
end;

function TIfxSmallFloatValue.GetAsSmallInt: int2;
begin
  Result := Round(GetValue);
end;

function TIfxSmallFloatValue.GetAsString: string;
begin
  Result := FloatToString(GetValue);
end;

function TIfxSmallFloatValue.GetAsVariant: Variant;
begin
  Result := GetValue;
end;

procedure TIfxSmallFloatValue.SetAsBCD(const Value: TBcd);
begin
  SetValue(LXBcdToDouble(Value));
end;

procedure TIfxSmallFloatValue.SetAsCurrency(Value: Currency);
begin
  SetValue(Value);
end;

procedure TIfxSmallFloatValue.SetAsDecimal(const Value: TDecimal);
begin
  SetValue(DecimalToFloat(Value));
end;

procedure TIfxSmallFloatValue.SetAsFloat(Value: Double);
begin
  SetValue(Value);
end;

procedure TIfxSmallFloatValue.SetAsInt8(const Value: TIfx_int8);
begin
  SetValue(Int8ToFloat(Value));
end;

procedure TIfxSmallFloatValue.SetAsInteger(Value: int4);
begin
  SetValue(Value);
end;

procedure TIfxSmallFloatValue.SetAsLargeint(Value: Largeint);
begin
  SetValue(Value);
end;

procedure TIfxSmallFloatValue.SetAsSmallFloat(Value: Single);
begin
  SetValue(Value);
end;

procedure TIfxSmallFloatValue.SetAsSmallInt(Value: int2);
begin
  SetValue(Value);
end;

procedure TIfxSmallFloatValue.SetAsString(const Value: string);
begin
  SetValue(StringToFloat(Value));
end;

procedure TIfxSmallFloatValue.SetAsVariant(const Value: Variant);
begin
  SetValue(Value);
end;

function TIfxSmallFloatValue.Format(const FmtStr: string): string;
begin
  Result := FloatToStringFmt(GetValue, FmtStr);
end;

procedure TIfxSmallFloatValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsSmallFloat(GetValue);
end;


{ TIfxDecimalValue }

function TIfxDecimalValue.GetValue: PDecimal;
begin
  Result := PDecimal(DataReadBuffer);
end;

procedure TIfxDecimalValue.SetValue(const Value: TDecimal);
begin
  Validate(@Value);
  PDecimal(DataWriteBuffer)^ := Value;
end;

function TIfxDecimalValue.GetBufferSize: Integer;
begin
  Result := SizeOf(TDecimal);
end;

function TIfxDecimalValue.GetAsBCD: TBcd;
begin
  Result := DecimalToBcd(GetValue^);
end;

function TIfxDecimalValue.GetAsCurrency: Currency;
begin
  Result := DecimalToCurrency(GetValue^);
end;

function TIfxDecimalValue.GetAsDecimal: TDecimal;
begin
  Result := GetValue^;
end;

function TIfxDecimalValue.GetAsFloat: Double;
begin
  Result := DecimalToFloat(GetValue^);
end;

function TIfxDecimalValue.GetAsInt8: TIfx_int8;
begin
  Result := DecimalToInt8(GetValue^);
end;

function TIfxDecimalValue.GetAsInteger: int4;
begin
  Result := DecimalToInt(GetValue^);
end;

function TIfxDecimalValue.GetAsLargeint: Largeint;
begin
  Result := DecimalToInt64(GetValue^);
end;

function TIfxDecimalValue.GetAsSmallFloat: Single;
begin
  Result := DecimalToFloat(GetValue^);
end;

function TIfxDecimalValue.GetAsSmallInt: int2;
begin
  Result := DecimalToSmallInt(GetValue^);
end;

function TIfxDecimalValue.GetAsString: string;
begin
  Result := DecimalToString(GetValue^);
end;

function TIfxDecimalValue.GetAsVariant: Variant;
begin
  Result := DecimalToVariant(GetValue^);
end;

procedure TIfxDecimalValue.SetAsBCD(const Value: TBcd);
begin
  SetValue(BcdToDecimal(Value));
end;

procedure TIfxDecimalValue.SetAsCurrency(Value: Currency);
begin
  SetValue(CurrencyToDecimal(Value));
end;

procedure TIfxDecimalValue.SetAsDecimal(const Value: TDecimal);
begin
  SetValue(Value);
end;

procedure TIfxDecimalValue.SetAsFloat(Value: Double);
begin
  SetValue(FloatToDecimal(Value));
end;

procedure TIfxDecimalValue.SetAsInt8(const Value: TIfx_int8);
begin
  SetValue(Int8ToDecimal(Value));
end;

procedure TIfxDecimalValue.SetAsInteger(Value: int4);
begin
  SetValue(IntToDecimal(Value));
end;

procedure TIfxDecimalValue.SetAsLargeint(Value: Largeint);
begin
  SetValue(Int64ToDecimal(Value));
end;

procedure TIfxDecimalValue.SetAsSmallFloat(Value: Single);
begin
  SetValue(FloatToDecimal(Value));
end;

procedure TIfxDecimalValue.SetAsSmallInt(Value: int2);
begin
  SetValue(SmallIntToDecimal(Value));
end;

procedure TIfxDecimalValue.SetAsString(const Value: string);
begin
  SetValue(StringToDecimal(Value));
end;

procedure TIfxDecimalValue.SetAsVariant(const Value: Variant);
begin
  SetValue(VariantToDecimal(Value));
end;

function TIfxDecimalValue.Format(const FmtStr: string): string;
begin
  Result := DecimalToStringFmt(GetValue^, FmtStr);
end;

procedure TIfxDecimalValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsDecimal(GetValue^);
end;


{ TIfxMoneyValue }

procedure TIfxMoneyValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsMoney(GetValue^);
end;


{ TIfxDateValue }

function TIfxDateValue.GetValue: int4;
begin
  Result := PInt4(DataReadBuffer)^;
end;

procedure TIfxDateValue.SetValue(Value: int4);
begin
  Validate(@Value);
  PInt4(DataWriteBuffer)^ := Value;
end;

function TIfxDateValue.GetBufferSize: Integer;
begin
  Result := SizeOf(int4);
end;

function TIfxDateValue.GetAsDate: int4;
begin
  Result := GetValue;
end;

function TIfxDateValue.GetAsDateTime: TDateTime;
begin
  Result := DateToDateTime(GetValue);
end;

function TIfxDateValue.GetAsDTime: TDTime;
begin
  Result := DateToDTime(GetValue);
end;

function TIfxDateValue.GetAsSqlTimeStamp: TSQLTimeStamp;
begin
  Result := DateToTimeStamp(GetValue);
end;

function TIfxDateValue.GetAsString: string;
begin
  Result := DateToString(GetValue);
end;

function TIfxDateValue.GetAsTime: TDateTime;
begin
  Result := 0;
end;

function TIfxDateValue.GetAsVariant: Variant;
begin
  Result := DateToDateTime(GetValue);
end;

procedure TIfxDateValue.SetAsDate(Value: int4);
begin
  SetValue(Value);
end;

procedure TIfxDateValue.SetAsDateTime(Value: TDateTime);
begin
  SetValue(DateTimeToDate(Value));
end;

procedure TIfxDateValue.SetAsDTime(const Value: TDTime);
begin
  SetValue(DTimeToDate(Value));
end;

procedure TIfxDateValue.SetAsSQLTimeStamp(const Value: TSQLTimeStamp);
begin
  SetValue(TimeStampToDate(Value));
end;

procedure TIfxDateValue.SetAsString(const Value: string);
begin
  SetValue(StringToDate(Value));
end;

procedure TIfxDateValue.SetAsTime(Value: TDateTime);
var
  mdy: array [0..2] of int2;
  Date: int4;
begin
  mdy[2] := 1899;
  mdy[0] := 12;
  mdy[1] := 30;
  CheckInformixResult(rmdyjul(@mdy, @Date));
  SetValue(Date);
end;

procedure TIfxDateValue.SetAsVariant(const Value: Variant);
begin
  SetValue(DateTimeToDate(Value));
end;

function TIfxDateValue.Format(const FmtStr: string): string;
begin
  Result := DateToStringFmt(GetValue, FmtStr);
end;

procedure TIfxDateValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsDate(GetValue);
end;


{ TIfxDTimeValue }

function TIfxDTimeValue.GetValue: PDTime;
begin
  Result := PDTime(DataReadBuffer);
end;

procedure TIfxDTimeValue.SetValue(const Value: TDTime);
begin
  Validate(@Value);
  PDTime(DataWriteBuffer)^ := Value;
end;

function TIfxDTimeValue.GetBufferSize: Integer;
begin
  Result := SizeOf(TDTime);
end;

function TIfxDTimeValue.GetAsDate: int4;
begin
  Result := DTimeToDate(GetValue^);
end;

function TIfxDTimeValue.GetAsDateTime: TDateTime;
begin
  Result := DTimeToDateTime(GetValue^);
end;

function TIfxDTimeValue.GetAsDTime: TDTime;
begin
  Result := GetValue^;
end;

function TIfxDTimeValue.GetAsSqlTimeStamp: TSQLTimeStamp;
begin
  Result := DTimeToTimeStamp(GetValue^);
end;

function TIfxDTimeValue.GetAsString: string;
begin
  Result := DTimeToString(GetValue^);
end;

function TIfxDTimeValue.GetAsTime: TDateTime;
begin
  Result := DTimeToTime(GetValue^);
end;

function TIfxDTimeValue.GetAsVariant: Variant;
begin
  Result := DTimeToDateTime(GetValue^);
end;

procedure TIfxDTimeValue.SetAsDate(Value: int4);
begin
  SetValue(DateToDTime(Value));
end;

procedure TIfxDTimeValue.SetAsDateTime(Value: TDateTime);
begin
  SetValue(DateTimeToDTime(Value));
end;

procedure TIfxDTimeValue.SetAsDTime(const Value: TDTime);
begin
  SetValue(Value);
end;

procedure TIfxDTimeValue.SetAsSQLTimeStamp(const Value: TSQLTimeStamp);
begin
  SetValue(TimeStampToDTime(Value));
end;

procedure TIfxDTimeValue.SetAsString(const Value: string);
begin
  SetValue(StringToDTime(Value, GetSize));
end;

procedure TIfxDTimeValue.SetAsTime(Value: TDateTime);
begin
  SetValue(TimeToDTime(Value));
end;

procedure TIfxDTimeValue.SetAsVariant(const Value: Variant);
begin
  SetValue(DateTimeToDTime(Value));
end;

function TIfxDTimeValue.Format(const FmtStr: string): string;
begin
  Result := DTimeToStringFmt(GetValue^, FmtStr);
end;

procedure TIfxDTimeValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsDTime(GetValue^);
end;


{ TIfxLocatorValue }

procedure TIfxLocatorValue.AllocateBuffer(var Buffer: PChar);
begin
  Buffer := AllocMem(SizeOf(TLoc));
  with PLoc(Buffer)^ do
  begin
    loc_loctype := LOCMEMORY;
    lc_union.lc_mem.lc_bufsize := -1;
    lc_union.lc_mem.lc_buffer := nil;
    loc_oflags := 0;
    lc_union.lc_mem.lc_mflags := LOC_ALLOC;
  end;
end;

procedure TIfxLocatorValue.FreeBuffer(Buffer: PChar);
begin
  if Buffer <> nil then
  begin
    with PLoc(Buffer)^.lc_union.lc_mem do
      if lc_mflags = 0 then
        FreeMem(lc_buffer) else
        SQLFreeMem(lc_buffer, STRING_FREE);
    FreeMem(Buffer);
  end;
end;

function TIfxLocatorValue.GetValue: PLoc;
begin
  Result := PLoc(DataReadBuffer);
end;

procedure TIfxLocatorValue.SetTypedValue(sqltype: int2; Size: Integer;
  Data: Pointer);
begin
  with PLoc(DataWriteBuffer)^, lc_union.lc_mem do
  begin
    loc_size := Size;
    lc_bufsize := Size;
    if lc_mflags = LOC_ALLOC then
      SQLFreeMem(lc_buffer, STRING_FREE) else
      FreeMem(lc_buffer);
    lc_buffer := nil;
    lc_mflags := 0;
    loc_type := sqltype;
    if Size > 0 then
    begin
      GetMem(lc_buffer, Size);
      if Data <> nil then
        Move(Data^, lc_buffer^, Size);
    end;
  end;
end;

function TIfxLocatorValue.GetBufferSize: Integer;
begin
  Result := SizeOf(TLoc);
end;

function TIfxLocatorValue.GetAsByte: TBlobByteData;
begin
  with GetValue^ do
  begin
    SetLength(Result, loc_size);
    Move(lc_union.lc_mem.lc_buffer^, Pointer(Result)^, loc_size);
  end;
end;

function TIfxLocatorValue.GetAsLocator: PLoc;
begin
  Result := GetValue;
end;

function TIfxLocatorValue.GetAsString: string;
begin
  with GetValue^ do
    SetString(Result, lc_union.lc_mem.lc_buffer, loc_size);
end;

function TIfxLocatorValue.GetAsVariant: Variant;
begin
  Result := GetAsString;
end;

procedure TIfxLocatorValue.SetAsByte(const Value: TBlobByteData);
begin
  SetTypedValue(SQLBYTES, Length(Value), PChar(Value));
end;

procedure TIfxLocatorValue.SetAsLocator(Value: PLoc);
begin
  if Value = nil then
    IDACError(SInvalidLocator);
  with Value^ do
    SetTypedValue(loc_type, loc_size, lc_union.lc_mem.lc_buffer);
end;

procedure TIfxLocatorValue.SetAsString(const Value: string);
begin
  SetTypedValue(SQLTEXT, Length(Value), PChar(Value));
end;

procedure TIfxLocatorValue.SetAsVariant(const Value: Variant);
begin
  SetAsByte(Value);
end;

procedure TIfxLocatorValue.SaveToStream(Stream: TStream);
begin
  with GetValue^ do
    Stream.WriteBuffer(lc_union.lc_mem.lc_buffer^, loc_size);
end;

procedure TIfxLocatorValue.LoadFromStream(Stream: TStream);
begin
  with GetValue^ do
  begin
    SetTypedValue(loc_type, Stream.Size - Stream.Position, nil);
    Stream.ReadBuffer(lc_union.lc_mem.lc_buffer^, loc_size);
  end;
end;

procedure TIfxLocatorValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsLocator(GetValue);
end;


{ TIfxIntervalValue }

function TIfxIntervalValue.GetValue: PIntrvl;
begin
  Result := PIntrvl(DataReadBuffer);
end;

procedure TIfxIntervalValue.SetValue(const Value: TIntrvl);
begin
  Validate(@Value);
  PIntrvl(DataWriteBuffer)^ := Value;
end;

function TIfxIntervalValue.GetBufferSize: Integer;
begin
  Result := SizeOf(TIntrvl);
end;

function TIfxIntervalValue.GetAsInterval: TIntrvl;
begin
  Result := GetValue^;
end;

function TIfxIntervalValue.GetAsString: string;
begin
  Result := IntervalToString(GetValue^);
end;

function TIfxIntervalValue.GetAsVariant: Variant;
begin
  Result := IntervalToString(GetValue^);
end;

procedure TIfxIntervalValue.SetAsInterval(const Value: TIntrvl);
begin
  SetValue(Value);
end;

procedure TIfxIntervalValue.SetAsString(const Value: string);
begin
  SetValue(StringToInterval(Value, GetSize));
end;

procedure TIfxIntervalValue.SetAsVariant(const Value: Variant);
begin
  SetAsString(Value);
end;

function TIfxIntervalValue.Format(const FmtStr: string): string;
begin
  Result := IntervalToStringFmt(GetValue^, FmtStr);
end;

procedure TIfxIntervalValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsInterval(GetValue^);
end;


{ TIfxInt8Value }

function TIfxInt8Value.GetValue: PIfx_int8;
begin
  Result := PIfx_int8(DataReadBuffer);
end;

procedure TIfxInt8Value.SetValue(const Value: TIfx_int8);
begin
  Validate(@Value);
  PIfx_int8(DataWriteBuffer)^ := Value;
end;

function TIfxInt8Value.GetBufferSize: Integer;
begin
  Result := SizeOf(TIfx_int8);
end;

function TIfxInt8Value.GetAsBCD: TBcd;
begin
  Result := Int8ToBcd(GetValue^);
end;

function TIfxInt8Value.GetAsCurrency: Currency;
begin
  Result := Int8ToInt64(GetValue^);
end;

function TIfxInt8Value.GetAsDecimal: TDecimal;
begin
  Result := Int8ToDecimal(GetValue^);
end;

function TIfxInt8Value.GetAsFloat: Double;
begin
  Result := Int8ToFloat(GetValue^);
end;

function TIfxInt8Value.GetAsInt8: TIfx_int8;
begin
  Result := GetValue^;
end;

function TIfxInt8Value.GetAsInteger: int4;
begin
  Result := Int8ToInt(GetValue^);
end;

function TIfxInt8Value.GetAsLargeint: Largeint;
begin
  Result := Int8ToInt64(GetValue^);
end;

function TIfxInt8Value.GetAsSmallFloat: Single;
begin
  Result := Int8ToSmallFloat(GetValue^);
end;

function TIfxInt8Value.GetAsSmallInt: int2;
begin
  Result := Int8ToSmallInt(GetValue^);
end;

function TIfxInt8Value.GetAsString: string;
begin
  Result := Int8ToString(GetValue^);
end;

function TIfxInt8Value.GetAsVariant: Variant;
begin
  Result := Int8ToString(GetValue^);
end;

procedure TIfxInt8Value.SetAsBCD(const Value: TBcd);
begin
  SetValue(BcdToInt8(Value));
end;

procedure TIfxInt8Value.SetAsCurrency(Value: Currency);
begin
  SetValue(CurrencyToInt8(Value));
end;

procedure TIfxInt8Value.SetAsDecimal(const Value: TDecimal);
begin
  SetValue(DecimalToInt8(Value));
end;

procedure TIfxInt8Value.SetAsFloat(Value: Double);
begin
  SetValue(FloatToInt8(Value));
end;

procedure TIfxInt8Value.SetAsInt8(const Value: TIfx_int8);
begin
  SetValue(Value);
end;

procedure TIfxInt8Value.SetAsInteger(Value: int4);
begin
  SetValue(IntToInt8(Value));
end;

procedure TIfxInt8Value.SetAsLargeint(Value: Largeint);
begin
  SetValue(Int64ToInt8(Value));
end;

procedure TIfxInt8Value.SetAsSmallFloat(Value: Single);
begin
  SetValue(SmallFloatToInt8(Value));
end;

procedure TIfxInt8Value.SetAsSmallInt(Value: int2);
begin
  SetValue(SmallIntToInt8(Value));
end;

procedure TIfxInt8Value.SetAsString(const Value: string);
begin
  SetValue(StringToInt8(Value));
end;

procedure TIfxInt8Value.SetAsVariant(const Value: Variant);
begin
  SetAsString(Value);
end;

procedure TIfxInt8Value.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsInt8(GetValue^);
end;


{ TIfxOpaqueValue }

class function TIfxOpaqueValue.IsEnabled: Boolean;
begin
  Result := Assigned(ifx_var_freevar);
end;

constructor TIfxOpaqueValue.Create(const BufferProvider: IIfxValueBufferProvider;
  AllocFlag: mint);
begin
  inherited Create(BufferProvider);
  FAllocFlag := AllocFlag;
end;

function TIfxOpaqueValue.GetValue: string;
var
  Buffer: PChar;
begin
  Buffer := DataReadBuffer;
  SetString(Result, PChar(ifx_var_getdata(@Buffer)), ifx_var_getlen(@Buffer) - 1);
end;

procedure TIfxOpaqueValue.SetValue(const Value: string);
var
  Buffer: PChar;
  Size: Integer;
begin
  Buffer := DataWriteBuffer;
  CheckInformixResult(ifx_var_dealloc(@Buffer));
  CheckInformixResult(ifx_var_flag(@Buffer, 0));
  if FAttached then
    ResetSubject.Detach(ResetBuffer);
  Size := Length(Value);
  CheckInformixResult(ifx_var_alloc(@Buffer, Size + 1));
  CheckInformixResult(ifx_var_setlen(@Buffer, Size));
  CheckInformixResult(ifx_var_setdata(@Buffer, PChar(Value), Size));
  CheckInformixResult(ifx_var_init(@Buffer));
end;

procedure TIfxOpaqueValue.ResetBuffer(Args: TObject);
var
  Buffer: PChar;
begin
  Buffer := DataReadBuffer;
  CheckInformixResult(ifx_var_dealloc(@Buffer));
end;

function TIfxOpaqueValue.GetBufferSize: Integer;
begin
  Result := 0;
end;

function TIfxOpaqueValue.GetAsString: string;
begin
  Result := GetValue;
end;

function TIfxOpaqueValue.GetAsVariant: Variant;
begin
  Result := GetValue;
end;

procedure TIfxOpaqueValue.SetAsString(const Value: string);
begin
  SetValue(Value);
end;

procedure TIfxOpaqueValue.SetAsVariant(const Value: Variant);
begin
  SetValue(Value);
end;

procedure TIfxOpaqueValue.AllocateBuffer(var Buffer: PChar);
begin
  CheckInformixResult(ifx_var_flag(@Buffer, 1));
  CheckInformixResult(ifx_var_init(@Buffer));
  if ResetSubject <> nil then
  begin
    ResetSubject.Attach(ResetBuffer);
    FAttached := True;
  end;
end;

procedure TIfxOpaqueValue.FreeBuffer(Buffer: PChar);
begin
  if FAttached then
    ResetSubject.Detach(ResetBuffer);
  CheckInformixResult(ifx_var_dealloc(@Buffer));
  CheckInformixResult(ifx_var_freevar(@Buffer));
end;

procedure TIfxOpaqueValue.SaveToStream(Stream: TStream);
var
  DataStr: string;
begin
  DataStr := GetValue;
  Stream.Write(PChar(DataStr)^, Length(DataStr));
end;

procedure TIfxOpaqueValue.LoadFromStream(Stream: TStream);
var
  DataStr: string;
begin
  SetString(DataStr, nil, Stream.Size - Stream.Position);
  if Length(DataStr) > 0 then
    Stream.ReadBuffer(PChar(DataStr)^, Length(DataStr));
  SetValue(DataStr);
end;

procedure TIfxOpaqueValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsOpaque(GetValue);
end;


{ TIfxLobBufferStrategy }

constructor TIfxLobBufferStrategy.Create(const ConnProvider: IIfxConnectionProvider);
begin
  FConnProvider := ConnProvider;
end;

function TIfxLobBufferStrategy.GetConnection: TIfxConnection;
begin
  if FConnProvider = nil then
    IDACError(SConnectionProviderRequired);
  Result := FConnProvider.Connection;
end;

procedure TIfxLobBufferStrategy.SetAsBuffer(Buffer: PChar; Size: Integer;
  Data: PChar);
var
  Lob: IIfxLob;
begin
  Lob := TIfxLob.Create(Connection);
  Lob.LoadFromBuffer(Size, Data);
  SetAsLob(Buffer, Lob);
end;

function TIfxLobBufferStrategy.GetBufferSize: Integer;
begin
  Result := SizeOf(TIfx_lo);
end;

procedure TIfxLobBufferStrategy.Copy(Source, Dest: PChar);
begin
  PIfx_lo(Dest)^ := PIfx_lo(Source)^;
end;

function TIfxLobBufferStrategy.RequiresCleanup: Boolean;
begin
  Result := False;
end;

procedure TIfxLobBufferStrategy.Cleanup(Buffer: PChar);
begin
end;

function TIfxLobBufferStrategy.GetAsByte(Buffer: PChar): TBlobByteData;
begin
  GetAsLob(Buffer).SaveToBuffer(Result, SetByteArraySize);
end;

function TIfxLobBufferStrategy.GetAsLob(Buffer: PChar): IIfxLob;
begin
  Result := TIfxLob.Create(Connection, PIfx_lo(Buffer)^);
end;

function TIfxLobBufferStrategy.GetAsString(Buffer: PChar): string;
begin
  GetAsLob(Buffer).SaveToBuffer(Result, SetStringSize);
end;

procedure TIfxLobBufferStrategy.SetAsByte(Buffer: PChar; const Value: TBlobByteData);
begin
  SetAsBuffer(Buffer, Length(Value), Pointer(Value));
end;

procedure TIfxLobBufferStrategy.SetAsLob(Buffer: PChar; const Value: IIfxLob);
begin
  PIfx_lo(Buffer)^ := Value.Handle^;
end;

procedure TIfxLobBufferStrategy.SetAsLocator(Buffer: PChar; Value: PLoc);
begin
  with Value^ do
    SetAsBuffer(Buffer, loc_size, lc_union.lc_mem.lc_buffer);
end;

procedure TIfxLobBufferStrategy.SetAsString(Buffer: PChar; const Value: string);
begin
  SetAsBuffer(Buffer, Length(Value), PChar(Value));
end;

procedure TIfxLobBufferStrategy.SaveToStream(Buffer: PChar; Stream: TStream);
begin
  GetAsLob(Buffer).SaveToStream(Stream);
end;

procedure TIfxLobBufferStrategy.LoadFromStream(Buffer: PChar; Stream: TStream);
var
  Lob: IIfxLob;
begin
  Lob := TIfxLob.Create(Connection);
  Lob.LoadFromStream(Stream);
  SetAsLob(Buffer, Lob);
end;

function TIfxLobBufferStrategy.CreateReadingStream(Buffer: PChar): TStream;
var
  Lob: IIfxLob;
begin
  Lob := GetAsLob(Buffer);
  Lob.Open(LO_RDONLY);
  Result := TIfxLobStream.Create(Lob);
end;


{ TIfxLobValue }

constructor TIfxLobValue.Create(const BufferProvider: IIfxValueBufferProvider;
  BufferStrategy: TIfxLobBufferStrategy);
begin
  inherited Create(BufferProvider);
  FBufferStrategy := BufferStrategy;
end;

function TIfxLobValue.GetBufferSize: Integer;
begin
  Result := FBufferStrategy.GetBufferSize;
end;

function TIfxLobValue.GetAsByte: TBlobByteData;
begin
  Result := FBufferStrategy.GetAsByte(DataReadBuffer);
end;

function TIfxLobValue.GetAsLob: IIfxLob;
begin
  Result := FBufferStrategy.GetAsLob(DataReadBuffer);
end;

function TIfxLobValue.GetAsString: string;
begin
  Result := FBufferStrategy.GetAsString(DataReadBuffer);
end;

function TIfxLobValue.GetAsVariant: Variant;
begin
  Result := GetAsString;
end;

procedure TIfxLobValue.SetAsByte(const Value: TBlobByteData);
begin
  FBufferStrategy.SetAsByte(DataWriteBuffer, Value);
end;

procedure TIfxLobValue.SetAsLob(const Value: IIfxLob);
begin
  if Value = nil then
    IDACError(SInvalidLob);
  FBufferStrategy.SetAsLob(DataWriteBuffer, Value);
end;

procedure TIfxLobValue.SetAsLocator(Value: PLoc);
begin
  if Value = nil then
    IDACError(SInvalidLocator);
  FBufferStrategy.SetAsLocator(DataWriteBuffer, Value);
end;

procedure TIfxLobValue.SetAsString(const Value: string);
begin
  FBufferStrategy.SetAsString(DataWriteBuffer, Value);
end;

procedure TIfxLobValue.SetAsVariant(const Value: Variant);
begin
  SetAsString(Value);
end;

procedure TIfxLobValue.FreeBuffer(Buffer: PChar);
begin
  FBufferStrategy.Cleanup(Buffer);
  FreeMem(Buffer);
end;

procedure TIfxLobValue.SaveToStream(Stream: TStream);
begin
  FBufferStrategy.SaveToStream(DataReadBuffer, Stream);
end;

procedure TIfxLobValue.LoadFromStream(Stream: TStream);
begin
  FBufferStrategy.SaveToStream(DataWriteBuffer, Stream);
end;


{ TIfxBlobValue }

procedure TIfxBlobValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.AsBlob := GetAsLob;
end;


{ TIfxClobValue }

procedure TIfxClobValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.AsClob := GetAsLob;
end;


{ TIfxBooleanValue }

function TIfxBooleanValue.GetValue: Boolean;
begin
  Result := Boolean(DataReadBuffer^);
end;

procedure TIfxBooleanValue.SetValue(Value: Boolean);
begin
  Validate(@Value);
  DataWriteBuffer^ := Char(Value);
end;

function TIfxBooleanValue.GetBufferSize: Integer;
begin
  Result := SizeOf(Boolean);
end;

function TIfxBooleanValue.GetAsBoolean: Boolean;
begin
  Result := GetValue;
end;

function TIfxBooleanValue.GetAsString: string;
begin
  if GetValue then Result := 't' else Result := 'f';
end;

function TIfxBooleanValue.GetAsVariant: Variant;
begin
  Result := GetValue;
end;

procedure TIfxBooleanValue.SetAsBoolean(Value: Boolean);
begin
  SetValue(Value);
end;

procedure TIfxBooleanValue.SetAsString(const Value: string);
begin
  SetValue(Value = 't');
end;

procedure TIfxBooleanValue.SetAsVariant(const Value: Variant);
begin
  SetValue(Value);
end;

procedure TIfxBooleanValue.AssignTo(const Dest: IIfxValue);
begin
  Dest.SetAsBoolean(GetValue);
end;


initialization
  globalNullValue := TIfxNullValue.Create;

finalization
  FreeAndNil(globalNullValue);

end.